續上一篇文章,寫到後面還有一些觀念沒有講得很清楚,像是var有Hoisting的特性,coding的時候常出現的undefined、not defined,今天一次把它搞懂。
中文翻譯是提升,網路有些文章對此的解釋是JavaScrip的變數和函示式,被提升到程式碼最上面,這樣的解釋好像還是不太理解,動手寫一段吧
var a = 'hello JavaScript!!';
function b(){
  console.log('console b');
}
console.log(a);
b();
預期console.log結果會跑出:
"hello JavaScript!!"
"console b"
這沒有問題,接下來把code改成這樣呢:
console.log(a);
b();
var a = 'hello JavaScript!!';
function b(){
  console.log('console b');
}
console.log結果:
undefined
"console b"
接下來我們把var a = 'hello JavaScript!!'給註解掉:
console.log(a);
b();
//var a = 'hello JavaScript!!';
function b(){
  console.log('console b');
}
console.log結果變成:
Uncaught ReferenceError: a is not defined
這個現象稱為 Hoisting。
以上都聽不懂很正常,接下來用其他方式講解
圖1.我們撰寫的JavaScript:
console.log(a);
b();
 var a = 'hello JavaScript!!';
function b(){
  console.log('console b');
}
console.log(a);//undefind
console.log('console b')//'console b'
經過JavaScript編譯,電腦看到的程式碼:
function b(){
  console.log('console b');
}
var a;
console.log(a);
b();
a = 'hello JavaScript!!';
var a進行宣告時把a這個變數存到記憶體裡面,JavaScript對所有變數預設都會是undefind,之後再給a變數賦予'hello JavaScript!!'這個字串。
執行環境開始運作時,會有兩個階段第一個是創建階段(Execution Context is Created):
設定變量和函數在記憶體這個步驟就叫做Hoisting,並不是真的把程式碼移到最上面,代表要逐步執行程式之前,JavaScript就已經把變數和函式放在記憶體裡建立一個空間,但是變數有點不一樣,當出現var a = 'hello JavaScript!!';(圖1)等號符號被設定時,JavaScript再為a空出一個記憶體時他不知道等號後面是什麼,所以預設會直接給他undefind這個特殊值。
JavaScript:
var a = 1;
console.log(a);// 1
//var a = 1;
console.log(a);// a not defined
依照剛剛複習的觀念,創建階段時並未宣告var a = 1,所以a變數從來沒有出現在記憶體中,a not defined就像是Browser裡的JavaScript跟你說:「 嘿,我沒有在`記憶體找到a這個值!」。
var a;
console.log(a);//undefined
當我們宣告var a,a在創造階段就會被放到記憶體中,並且JavaScript會直接賦予undefined給a,所以undefined不代表空或是還沒定義,undefined是個特殊的值,也會佔據記憶體空間。
開發時請記得不要把變數設值為undefind:
var a = 'hello world!!';
console.log(a); //hello world!!
a = undefined;
console.log(a); //a = undefined
當程式碼變多時,你會無法分辨undefined是JavaScrip預設給的,還是你後來自己設定的。
##結論
undefined不等於not defined
undefined``是已經宣告變數了,JavaScript給的預設值。not defined是創建環境時,沒有宣告加入記憶體,JavaScript找不到這個值。